package jmine.tec.environment;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;

/**
 * Classe que implementa a interface <code>Callable</code> e permite que diversos <code>Callable</code>s sejam executados em sequência
 * aproveitando um mesmo ambiente.
 * 
 * @author Cesar Olmos
 * @param <T> o tipo de retorno dos <code>Callable</code>s
 */
public class EnvironmentCaller<T> implements Callable<List<T>>, Serializable {
    private Environment environment;

    private List<? extends Callable<T>> callables;

    /**
     * Construtor.
     * 
     * @param environment o ambiente de execução.
     * @param callables os <code>Callable</code>s que devem ser executados.
     */
    public EnvironmentCaller(Environment environment, List<? extends Callable<T>> callables) {
        this.environment = environment;
        this.callables = callables;
    }

    /**
     * Executa cada um dos <code>Callable</code>s, garantindo os controles de start, stop e restart no ambiente de execução.
     * 
     * @return uma lista com os retornos das chamadas de cada um dos <code>Callable</code>s.
     * @throws Exception caso ocorra algum erro.
     */
    public List<T> call() throws Exception {
        this.environment.start();
        boolean started = false;

        List<T> results = new ArrayList<T>(this.callables.size());
        for (Callable<T> callable : callables) {
            if (!started) {
                this.environment.restart();
                started = true;
            }
            results.add(callable.call());
        }

        this.environment.stop();
        return results;
    }

}
